package j.framework.util;

import j.framework.core.DataType;
import j.util.DateUtils;
import j.util.StringUtils;

import java.sql.Time;
import java.text.NumberFormat;
import java.text.ParseException;

/**
 * 基本数据类型转换工具类
 * @author Junhai, LIu
 *
 */
public final class ConvertUtils {

	/**
	 * 将boolean型的数据转换为字符型,即"true"或"false"
	 * @param b
	 * @return
	 */
	public static String toString(boolean b){
		if(b){
			return "true";
		}
		return "false";
	}
	
	/**
	 * 将int类型的数据转换为字符型
	 * @param intNumber
	 * @return
	 */
	public static String toString(int intNumber){
		return String.valueOf(intNumber);
	}
	
	/**
	 * 将double类型的数据转换为字符类型
	 * @param doubleNumber
	 * @return
	 */
	public static String toString(double doubleNumber){
		return String.valueOf(doubleNumber);
	}
	
	/**
	 * 将float类型的数据转换为字符类型
	 * @param floatNumber
	 * @return
	 */
	public static String toString(float floatNumber){
		return String.valueOf(floatNumber);
	}
	
	/**
	 * 将long类型的数据转换为字符类型
	 * @param longNumber
	 * @return
	 */
	public static String toString(long longNumber){
		return String.valueOf(longNumber);
	}
	
	/**
	 * 将Object类型的数据转换为字符类型
	 * @param obj
	 * @return
	 */
	public static String toString(Object obj){
		return String.valueOf(obj);
	}

	public static Byte toByte(String byteInput){
		try{
			return NumberFormat.getInstance().parse(byteInput).byteValue();
		}catch (ParseException ignored){}
		return null;
	}

	/**
	 * 将字符串型的byte类型转换为byte,首先将字符串转换为number类型,然后再转换为byte
	 * @param byteInput
	 * @return
	 */
	public static byte toByteValue(String byteInput,byte defaultValue){
		if(StringUtils.isNullOrEmpty(byteInput)){
			return defaultValue;
		}
		try{
			return NumberFormat.getInstance().parse(byteInput).byteValue();
		}catch(ParseException ignored){}
		return defaultValue;
	}

	public static Short toShort(String shortInput){
		try{
			return NumberFormat.getInstance().parse(shortInput).shortValue();
		}catch (Exception ignored){}
		return null;
	}
	public static short toShortValue(String shortInput,short defaultValue){
		try{
			return NumberFormat.getInstance().parse(shortInput).shortValue();
		}catch (ParseException ignored){}
		return defaultValue;
	}
	public static short toShortValue(String shortInput){
		try{
			return NumberFormat.getInstance().parse(shortInput).shortValue();
		}catch (ParseException ignored){
            throw new RuntimeException("不能将输入值"+shortInput+"转换成短整型！");
        }
	}

	/**
	 * 将指定的数字字符串类型的输入转换为整形，若转换失败，则转换为null
	 * @param intStrInput
	 * @return
	 */
	public static Integer toInteger(String intStrInput){
		NumberFormat nf = NumberFormat.getInstance();
		try{
			Number n = nf.parse(intStrInput);
			return n.intValue();
		}catch(ParseException e){
			return null;
		}
	}

	/**
	 * 将给定的字符串(sint)转换为整型,如果该字符串不能成功转换,将默认值返回
	 * 如果sint是带小数的字符串的数字形式,则只将小数点后的数字去掉转换成的整型
	 * @param sint 包含要转换数字的字符串
	 * @param defaultValue sint不能成功转换时的默认值
	 * @return
	 */
	public static int toInt(String sint, int defaultValue){
        if(StringUtils.isNullOrEmpty(sint)){
            return defaultValue;
        }
		NumberFormat nf = NumberFormat.getInstance();
		Number n = null;
		int _ret = defaultValue;
		try{
			n = nf.parse(sint);
			_ret = n.intValue();
		}catch(ParseException e){
			_ret = defaultValue;
		}
		return _ret;
	}
	
	/**
	 * 将给定的字符串(sint)转换为整型,如果该字符串不能成功转换,则抛出异常
	 * 如果sint是带小数的字符串的数字形式,则只将小数点后的数字去掉转换成的整型
	 * @param sint 包含要转换数字的字符串
	 * @return
	 */
	public static int toInt(String sint){
		if(StringUtils.isNullOrEmpty(sint)){
			throw new RuntimeException("类型转换异常:包含要转换数字的字符串不能为空!");
		}
		NumberFormat nf = NumberFormat.getInstance();
		Number n = null;
		try{
			n = nf.parse(sint);
		}catch(ParseException e){
			throw new RuntimeException("类型转换异常:不能将字符串\""+sint+"\"转换为整型!");
		}
		return n.intValue();
	}
	
	/**
	 * 将给定的对象(能正确转换为整型的对象)转换为所对应的整型,如果不能成功转换,则抛出异常
	 * @param oint 包含要转换数字的对象
	 * @return
	 */
	public static int toInt(Object oint){
		if(null == oint){
			throw new RuntimeException("类型转换异常:包含要转换数字的对象不能为空!");
		}
		return toInt(oint.toString());
	}
	
	/**
	 * 将给定的对象(能正确转换为整型的对象)转换为所对应的整型,如果该对象不能成功转换,将默认值返回
	 * @param oint 包含要转换数字的对象
	 * @param defaultValue 对象转换失败时所返回的默认值
	 * @return
	 */
	public static int toInt(Object oint, int defaultValue){
		if(null == oint){
			return defaultValue;
		}
		return toInt(oint.toString(), defaultValue);
	}

	/**
	 * 将指定的字符串类型的长整形数字转换为长整形
	 * @param slong
	 * @return
	 */
	public static Long toLong(String slong){
		NumberFormat nf = NumberFormat.getInstance();
		try {
			Number n = nf.parse(slong);
			return n.longValue();
		} catch (ParseException ignored) {}
		return null;
	}
	
	/**
	 * 转换为长整形,若slong为空或非法,则返回0
	 * @param slong
	 * @return
	 */
	public static long toLongValue(String slong){
		return toLongValue(slong, 0L);
	}
	
	/**
	 * 转换为长整形,若slong为空或非法,则返回defaultValue
	 * @param slong
	 * @param defaultValue
	 * @return
	 */
	public static long toLongValue(String slong,long defaultValue){
		if(StringUtils.isNullOrEmpty(slong)){
			return defaultValue;
		}
		NumberFormat nf = NumberFormat.getInstance();
		try {
			Number n = nf.parse(slong);
			return n.longValue();
		} catch (ParseException ignored) {}
		return defaultValue;
	}

    public static long toLongValue(Object obj,long defaultValue){
        return toLongValue(String.valueOf(obj), defaultValue);
    }

	/**
	 * 将指定的字符串类型的长整形数字转换为长整形
	 * @param sdbl
	 * @return
	 */
	public static Double toDouble(String sdbl){
		NumberFormat nf = NumberFormat.getInstance();
		try {
			Number n = nf.parse(sdbl);
			return n.doubleValue();
		} catch (ParseException ignored) {}
		return null;
	}

	/**
	 * 将给定的字符串(sdbl)转换为双精度类型,如果该字符串不能成功转换,将默认值返回
	 * @param sdbl 包含要转换双精度类型的字符串
	 * @param defaultValue sint不能成功转换时的默认值
	 * @return
	 */
	public static double toDoubleValue(String sdbl, double defaultValue){
		if(StringUtils.isNullOrEmpty(sdbl)){
			return defaultValue;
		}
		NumberFormat nf = NumberFormat.getInstance();
		Number n = null;
		double _ret = defaultValue;
		try{
			n = nf.parse(sdbl);
			_ret = n.doubleValue();
		}catch(ParseException e){
			_ret = defaultValue;
		}
		return _ret;
	}
	
	/**
	 * 将给定的字符串(sdbl)转换为双精度,如果该字符串不能成功转换,则抛出异常
	 * @param sdbl 包含要转换数字的字符串
	 * @return
	 */
	public static double toDoubleValue(String sdbl){
		if(StringUtils.isNullOrEmpty(sdbl)){
			throw new RuntimeException("类型转换异常:包含要转换数字的字符串不能为空!");
		}
		NumberFormat nf = NumberFormat.getInstance();
		Number n = null;
		try{
			n = nf.parse(sdbl);
		}catch(ParseException e){
			throw new RuntimeException("类型转换异常:不能将sint转换为整型!");
		}
		return n.doubleValue();
	}
	
	/**
	 * 将给定的对象(能正确转换为双精度的对象)转换为所对应的双精度整型,如果不能成功转换,则抛出异常
	 * @param odbl 包含要转换数字的对象
	 * @return
	 */
	public static double toDoubleValue(Object odbl){
		if(null == odbl){
			throw new RuntimeException("类型转换异常:包含要转换数字的对象不能为空!");
		}
		return toDoubleValue(odbl.toString());
	}
	
	/**
	 * 将给定的对象(能正确转换为整型的对象)转换为所对应的整型,如果该对象不能成功转换,将默认值返回
	 * @param odbl 包含要转换数字的对象
	 * @param defaultValue 对象转换失败时所返回的默认值
	 * @return
	 */
	public static double toDoubleValue(Object odbl, double defaultValue){
		if(null == odbl){
			return defaultValue;
		}
		return toDoubleValue(odbl.toString(), defaultValue);
	}

	public static Float toSingle(String sflt){
		try {
			return NumberFormat.getInstance().parse(sflt).floatValue();
		}catch (ParseException ignored){
		}
		return null;
	}
	
	/**
	 * 将给定的字符串(sdbl)转换为单精度类型,如果该字符串不能成功转换,将默认值返回
	 * @param sflt 包含要转换单精度类型的字符串
	 * @param defaultValue sflt不能成功转换时的默认值
	 * @return
	 */
	public static float toSingleValue(String sflt, float defaultValue){
		if(StringUtils.isNullOrEmpty(sflt)){
			return defaultValue;
		}
		NumberFormat nf = NumberFormat.getInstance();
		Number n = null;
		float _ret = defaultValue;
		try{
			n = nf.parse(sflt);
			_ret = n.floatValue();
		}catch(ParseException e){
			_ret = defaultValue;
		}
		return _ret;
	}
	
	/**
	 * 将给定的字符串(sflt)转换为单精度,如果该字符串不能成功转换,则抛出异常
	 * @param sflt 包含要转换数字的字符串
	 * @return
	 */
	public static float toSingleValue(String sflt){
		if(StringUtils.isNullOrEmpty(sflt)){
			throw new RuntimeException("类型转换异常:包含要转换数字的字符串不能为空!");
		}
		NumberFormat nf = NumberFormat.getInstance();
		Number n = null;
		try{
			n = nf.parse(sflt);
		}catch(ParseException e){
			throw new RuntimeException("类型转换异常:不能将sflt转换为单精度类型!");
		}
		return n.floatValue();
	}
	
	/**
	 * 将给定的对象(能正确转换为单精度的对象)转换为所对应的单精度整型,如果不能成功转换,则抛出异常
	 * @param oflt 包含要转换数字的对象
	 * @return
	 */
	public static float toSingleValue(Object oflt){
		if(null == oflt){
			throw new RuntimeException("类型转换异常:包含要转换数字的对象不能为空!");
		}
		if(oflt instanceof Float){
			return (float)oflt;
		}else{
			return toSingleValue(oflt.toString());
		}
	}
	
	/**
	 * 将给定的对象(能正确转换为整型的对象)转换为所对应的整型,如果该对象不能成功转换,将默认值返回
	 * @param oflt 包含要转换数字的对象
	 * @param defaultValue 对象转换失败时所返回的默认值
	 * @return
	 */
	public static float toSingleValue(Object oflt, float defaultValue){
		if(null == oflt){
			return defaultValue;
		}
		return toSingleValue(oflt.toString(), defaultValue);
	}
	
	/**
	 * 将给定的字符串转换为所对应的布尔值,如果该值为空,则返回false
	 * 仅当给定的字符串为:true,yes,ok,on,1字符串时才转换为true,其它均转换为false
	 * @param sbool 待转换为布尔的字符串
	 * @return
	 */
	public static boolean toBoolean(String sbool){
		if(StringUtils.isNullOrEmpty(sbool)){
			return false;
		}
		boolean ret = false;
		String _s = sbool.toLowerCase();
		if("true".equals(_s)){
			ret = true;
		}else if("yes".equals(_s)){
			ret = true;
		}else if("on".equals(_s)){
			ret = true;
		}else if("ok".equals(_s)){
			ret = true;
		}else if("1".equals(_s)){
			ret = true;
		}
		return ret;
	}

    /**
     * 将指定的输入值转换为正确的数据类型
     * @param inputValue
     * @param dataType
     * @return
     */
    public static Object convertToCorrectData(String inputValue,DataType dataType){
        if(StringUtils.isNullOrEmpty(inputValue)){
            return null;
        }
        if(dataType.equals(DataType.STRING)){
            return inputValue;
        }
        try{
            if(dataType.equals(DataType.INTEGER)){
                return toInt(inputValue);
            }else if(dataType.equals(DataType.FLOAT)){
                return toSingle(inputValue);
            }else if(dataType.equals(DataType.DOUBLE)){
                return toDouble(inputValue);
            }else if(dataType.equals(DataType.DATE)){
                return DateUtils.toDate(inputValue, "yyyy-MM-dd");
            }else if(dataType.equals(DataType.DATETIME)){
                String dateFormat = "yyyy-MM-dd";
                String[] arr = inputValue.split(":");
                if(arr.length == 1){
                    //再检测一下有没有小时
                    arr = inputValue.split("\\s");
                    if(arr.length == 2){
                        //仅有小时，没有分及秒
                        dateFormat += " HH";
                    }
                }else if(arr.length == 2){
                    //有小时，有分，但没有秒
                    dateFormat += " HH:mm";
                }else if(arr.length == 3){
                    //有小时，有分，也有秒
                    dateFormat += " HH:mm:ss";
                }
                return DateUtils.toDate(inputValue, dateFormat);
            }else if(dataType.equals(DataType.TIME)){
                String[] arr = inputValue.split(":");
                String vv = inputValue;
                if(arr.length == 2){
                    vv += ":00";
                }
                return Time.valueOf(vv);
            }else if(dataType.equals(DataType.LONG)){
                return toLongValue(inputValue);
            }else if(dataType.equals(DataType.SHORT)){
                return toShortValue(inputValue);
            }else if(dataType.equals(DataType.BOOLEAN)){
                return toBoolean(inputValue);
            }
            return inputValue;
        }catch (Exception e){
            throw new RuntimeException("数据["+inputValue+"]输入有错，请输入正确的数据类型["+dataType.toString()+"]");
        }
    }
}
